Categories
Vue 3

Form Validation in a Vue 3 App with Vee-Validate 4 — useForm and Dynamic Forms

Spread the love

Form validation is an important part of any app.

In this article, we’ll look at how to use Vee-Validate 4 in our Vue 3 app for form validation.

useForm()

The useForm() function lets us create form context that we can use to create reactive forms.

To use it, we write:

<template>
  <form @submit="onSubmit">
    <Field name="email" />
    <span>{{ errors.email }}</span>
    <br />

    <Field name="password" />
    <span>{{ errors.password }}</span>
    <br />

    <input type="submit" />
  </form>
</template>

<script>
import { Field, useForm } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Field,
  },
  setup() {
    const { handleSubmit, errors } = useForm({
      validationSchema: yup.object().shape({
        email: yup.string().required().email(),
        password: yup.string().required().min(3),
      }),
    });
    const onSubmit = handleSubmit((values, actions) => {
      alert(JSON.stringify(values, null, 2));
      actions.resetForm();
    });

    return {
      errors,
      onSubmit,
    };
  },
};
</script>

We call the useForm function with the validationSchema property to set the validation schema.

email and password are the name attribute values of the fields.

It returns an object with the handleSubmit function and the errors object with the form validation errors.

We use errors in the form.

And we call handleSubmit with a callback to handle submissions.

values has the inputted values.

actions has the resetForm method to reset the validation status of the form.

We can set the initial values of the form fields.

To do this, we write:

<template>
  <form @submit="onSubmit">
    <Field name="email" />
    <span>{{ errors.email }}</span>
    <br />

    <Field name="password" />
    <span>{{ errors.password }}</span>
    <br />

    <input type="submit" />
  </form>
</template>

<script>
import { Field, useForm } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Field,
  },
  setup() {
    const { handleSubmit, errors } = useForm({
      initialValues: {
        email: "abc@abc.com",
        password: "",
      },
      validationSchema: yup.object().shape({
        email: yup.string().required().email(),
        password: yup.string().required().min(3),
      }),
    });
    const onSubmit = handleSubmit((values, actions) => {
      alert(JSON.stringify(values, null, 2));
      actions.resetForm();
    });

    return {
      errors,
      onSubmit,
    };
  },
};
</script>

to add the initialValues property into the object we pass into useForm to set the value of the email field.

Dynamic Form

We can use Vee-Validate 4 to validate dynamically rendered forms.

For example, we can write:

<template>
  <Form v-slot="{ errors }" :validation-schema="schema.validation">
    <div v-for="field in schema.fields" :key="field.name">
      <label :for="field.name">{{ field.label }}</label>
      <Field :as="field.as" :id="field.name" :name="field.name" />
      <span>{{ errors[field.name] }}</span>
    </div>

    <button>Submit</button>
  </Form>
</template>

<script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";

export default {
  components: {
    Form,
    Field,
  },
  data() {
    return {
      schema: {
        fields: [
          {
            label: "Name",
            name: "name",
            as: "input",
          },
          {
            label: "Email",
            name: "email",
            as: "input",
          },
          {
            label: "Password",
            name: "password",
            as: "input",
          },
        ],
        validation: yup.object().shape({
          email: yup.string().email().required(),
          name: yup.string().required(),
          password: yup.string().min(8).required(),
        }),
      },
    };
  },
};
</script>

In the data method, we return an object with the schema reactive property.

It has the data to render the fields in the fields array.

We use it to render the label and name and what to render the Field as with the as property.

The validation property has the validation schema for our fields.

In the template, we render the items and display the errors in the span .

This is more convenient than adding each field into our template.

Conclusion

We can create forms with the useForm function.

And we can create dynamic forms with validation in our Vue 3 app with Vee-Validate 4.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *